package com.hyc.gchatsystem.redis;

import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.redis.*;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * @projectName: gchatsystem
 * @package: com.hyc.gchatsystem.redis
 * @className: RedisClientHandler
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/4/15 20:04
 * @version: 1.0
 */
// 要实现出入栈 所以我们需要实现混合的处理器类
public class RedisClientHandler extends ChannelDuplexHandler {

    // 写
    // 出栈handler 的常用方法
    //需要处理redis 命令
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        // 键盘传入的字符串 如 ： keys *
        String commandStr = (String) msg;
        // 通过空格来分离出命令
        String[] commandArr = commandStr.split("\\s+");
        // 接受redis 命令的列表  RedisMessag保存命令的内容
        List<RedisMessage> redisMessageList = new ArrayList<>(commandArr.length);
        for (String cmdStr : commandArr) {
            FullBulkStringRedisMessage message = new FullBulkStringRedisMessage(
                    ByteBufUtil.writeUtf8(ctx.alloc(), cmdStr));
            redisMessageList.add(message);
        }
        //将分离的命令 合并成一个完整的命令
        RedisMessage request = new ArrayRedisMessage(redisMessageList);
        //写入通道
        ctx.write(request, promise);
    }

    // 读取
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 此时接受的时候这个值 就是我们存储redismessage 的对象
        RedisMessage redisMessage = (RedisMessage) msg;
        // 返回的结果是不同类型 分开进行处理
        printRedisResponse(redisMessage);
        //    内存管理使用了 引用计数的方式 所以我们需要释放资源
        ReferenceCountUtil.release(redisMessage);
    }

    private void printRedisResponse(RedisMessage msg) {
        if (msg instanceof SimpleStringRedisMessage) {
            SimpleStringRedisMessage tmpMsg = (SimpleStringRedisMessage) msg;
            System.out.println(tmpMsg.content());
        } else if (msg instanceof ErrorRedisMessage) {
            ErrorRedisMessage tmpMsg = (ErrorRedisMessage) msg;
            System.out.println(tmpMsg.content());
        } else if (msg instanceof IntegerRedisMessage) {
            IntegerRedisMessage tmpMsg = (IntegerRedisMessage) msg;
            System.out.println(tmpMsg.value());
        } else if (msg instanceof FullBulkStringRedisMessage) {
            FullBulkStringRedisMessage tmpMsg = (FullBulkStringRedisMessage) msg;
            if (tmpMsg.isNull()) {
                return;
            }
            System.out.println(tmpMsg.content().toString(CharsetUtil.UTF_8));
        } else if (msg instanceof ArrayRedisMessage) {
            ArrayRedisMessage tmpMsg = (ArrayRedisMessage) msg;
            for (RedisMessage child : tmpMsg.children()) {
                printRedisResponse(child);
            }
        }
        // 如果都是不是应该抛出异常
    }

    // 异常处理
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }


}
